#include <vcl.h>
#include "eic.h"
#pragma hdrstop

#include "CEditMon.h"
//#pragma link "CEdit"
#pragma package(smart_init)



// Nombre de decimales : par defaut 2
int CEditMontant::iNbDecimales = CurrencyDecimals;

//---------------------------------------------------------------------------
namespace Ceditmon
{
 #define _strEspace ThousandSeparator
 #define _strMoins "-"

	void __fastcall PACKAGE Register()
	{
		TComponentClass classes[1] = {__classid(CEditMontant)};
		RegisterComponents("EIC Ctrlstd", classes, 0);
	}



//********************//
// Class CEditMontant //
//********************//////////////////////////////////////////////////////////
//                                                                            //
//    Cette classe implémente un control de saisie/affichage d'un montant     //
// monétaire au format "ddd ddd,dd" sans symbole indicateur de la devise (les //
// séparateurs de milliers et de décimales - supposés être ' ' et ',' -       //
// doivent être positionnés via les variables globales CurrencyString,        //
// CurrencyDecimals, ThousandSeparator et DecimalSeparator).                  //
//                                                                            //
// PARTICULARITÉS :                                                           //
//    Les montants négatifs sont signés à droite (variable globale            //
// NegCurrFormat) et la saisie/l'affichage est cadré à droite.                //
////////////////////////////////////////////////////////////////////////////////
__fastcall CEditMontant::CEditMontant( TComponent* pOwner)
: inherited( pOwner)
{
 // Seuls les chiffres sont - par défaut - acceptés
 inherited::Filtres << feNumerique;
 ASSERT( inherited::Filtres == ( FiltresEdit() << feNumerique));

 // Les autres caractères en saisie sont filtrés via "OnIllegalChar"
 inherited::OnIllegalChar = OnIllegalChar;

 // L'alignement est à droite par défaut
 inherited::Alignment = taRightJustify;

 // Largeur par défaut pour afficher en gras "9 999 999,99"
 if( iNbDecimales == 2 )
	inherited::Width     = 113;
 else
	inherited::Width     = 125;

 // Par défaut, pas de possibilité de saisir en négatif
 m_bNegatif = false;


} /* CEditMontant::CEditMontant() */


/*----------------------------------------------------------------------------*\
------------- CEditMontant::OnIllegalChar() ------------------------------------
--------------------------------------------------------------------------------
-                                                                              -
-    Cette méthode permet de mettre à jour l'attribut m_dtDate et de refléter  -
- le changement sur le control.                                                -
-                                                                              -
- Paramètres :                                                                 -
-   pedSender        : Le control de saisie du montant.                        -
-   cIllegalCharCode : Code (virtuel) du caractère à saisir.                   -
-   bAccept          : Positionner à true pour accepter le caractère           -
-                      (éventuellemnt modifié) en saisie.                      -
-                                                                              -
- Notes : * Un caractère refusé provoque un beep pour avertir l'utilisateur.   -
-         * L'acceptation du caractère '\0' n'a aucun effet sur la saisie.     -
\*----------------------------------------------------------------------------*/
void __fastcall CEditMontant::OnIllegalChar( CCustomEdit* pedSender,
                                             Word&        cIllegalCharCode,
                                             bool&        bAccept)
{
 switch( cIllegalCharCode)
 { ////////////////////////////////////
   // Filtrage du séparateur décimal //
   ////////////////////////////////////
   case ';' :
   case '.' :
   case ':' :
   case ',' :
	 {
	   DWORD      dwCaretPos0;
	   AnsiString strCurMontant( SolveSelection( dwCaretPos0));

	   if( strchr( strCurMontant.c_str(), /*','*/DecimalSeparator) != NULL)
	   { // Le montant a déjà un séparateur décimal
		 // => Séparateur refusé
		 break;
	   }

	   if( dwCaretPos0 == 0)
	   { // On insère le séparateur au début du montant
		 // => On rajoute un zéro devant le séparateur
		 ASSERT( dwCaretPos0 == 0);
		 strCurMontant.Insert( "0", 1);
		 dwCaretPos0 = 2;
	   }
	   else
	   { // Le montant n'a pas encore de séparateur décimal
		 // => On accepte le séparateur
		 dwCaretPos0++;
	   }

	   // Insertion du séparateur
	   strCurMontant.Insert( /*","*/AnsiString( DecimalSeparator), dwCaretPos0);
	   Text = strCurMontant;

	   // Repositionnement du caret
	   Perform( EM_SETSEL, dwCaretPos0, dwCaretPos0);

	   // Le séparateur décimal est valide mais ne doit pas être traité
	   cIllegalCharCode = '\0';
	   bAccept          = true;
	 }
	 break;


   ///////////////////////////////
   // Filtrage du signe négatif //
   ///////////////////////////////
   case '-' :
   case '+' : // Le signe positif annule l'éventuel signe négatif
	 if( m_bNegatif)
	 {
	   DWORD       dwCaretPos0;
	   AnsiString  strCurMontant( SolveSelection( dwCaretPos0));
	   const char* pcszMontant;

	   // Ajout/suppression du signe négatif
	   if( *( pcszMontant = strCurMontant.c_str()) == '-')
	   { // Suppression du signe négatif
		 dwCaretPos0--;
		 Text = pcszMontant + 1;
	   }
	   else if( cIllegalCharCode == '-')
	   { // Ajout du signe négatif
		 dwCaretPos0++;
		 Text = _strMoins + strCurMontant;
	   }
	   else
	   { // Signe positif avec un montant déjà positif
		 // => Caractère interdit
		 break;
	   }

	   // Repositionnement du caret
	   Perform( EM_SETSEL, dwCaretPos0, dwCaretPos0);

	   // Le signe négatif est valide mais ne doit pas être traité
	   cIllegalCharCode = '\0';
	   bAccept          = true;
	 }
	 break;


   ///////////////////////////////////
   // Filtrage des touches standard //
   ///////////////////////////////////
   case VK_BACK :
	 bAccept = true;
	 break;
 }
} /* CEditMontant::OnIllegalChar() */


/*----------------------------------------------------------------------------*\
------------- CEditMontant::SetMontant() ---------------------------------------
--------------------------------------------------------------------------------
-                                                                              -
-    Cette méthode permet d'initialiser le montant à afficher.                 -
-                                                                              -
- Paramètres :                                                                 -
-   curMontant : Montant à afficher dans le control.                           -
\*----------------------------------------------------------------------------*/
void __fastcall CEditMontant::SetMontant( const Currency& curMontant)
{
bool bOldModified = Modified;

 Text = FloatToStrF( curMontant, ffCurrency, 16, iNbDecimales);
 Modified = bOldModified;
// Text = CurrToStr( curMontant);
} /* CEditMontant::SetMontant() */


/*----------------------------------------------------------------------------*\
------------- CEditMontant::GetMontant() ---------------------------------------
--------------------------------------------------------------------------------
-                                                                              -
-    Cette méthode permet d'obtenir la valeur du montant affiché dans le       -
- control.                                                                     -
\*----------------------------------------------------------------------------*/
const Currency __fastcall CEditMontant::GetMontant( void)
{
 AnsiString strMontant( (const AnsiString&)Text);
 int        nPos;


 //////////////////////////
 // Nettoyage du montant //
 //////////////////////////
 // Suppression des blancs (séparateurs de milliers) pour la fonction StrToCurr
 if( ( nPos = strMontant.Pos( "F")) > 0)
   strMontant.Delete( nPos, 1);
 while( ( nPos = strMontant.Pos( _strEspace)) > 0)
   strMontant.Delete( nPos, 1);

 // L'éventuel signe négatif est toujours à gauche du montant
 ASSERT( strMontant.Pos( _strMoins) <= 1);
/*
 // Repositionnement du signe négatif
 if( ( nPos = strMontant.Pos( _strMoins)) > 0)
 { // En affichage, le signe négatif est placé à la fin du montant
   // => Transfert du signe négatif au début de la somme (pour la fonction StrToCurr)
   strMontant.Delete( nPos, 1);
   strMontant.Insert( _strMoins, 1);
 }
*/

 Currency curMontant( 0);
 try {
   curMontant = ( strMontant.IsEmpty() || ( strMontant == _strMoins)) ? Currency( (int)0) : StrToCurr( strMontant);
 } catch( EConvertError &e) {
 }

 return curMontant;
} /* CEditMontant::GetMontant() */


/******************************************************************************\
************* CEditMontant::operator+=() ***************************************
********************************************************************************
*                                                                              *
*    Cet opérateur permet d'ajouter une valeur au montant affiché.             *
\******************************************************************************/
void __fastcall CEditMontant::operator+=( const Currency& curVal)
{
 SetMontant( GetMontant() + curVal);
} /* CEditMontant::operator+=() */


/******************************************************************************\
************* CEditMontant::operator-=() ***************************************
********************************************************************************
*                                                                              *
*    Cet opérateur permet de retrancher une valeur au montant affiché.         *
\******************************************************************************/
void __fastcall CEditMontant::operator-=( const Currency& curVal)
{
 SetMontant( GetMontant() - curVal);
} /* CEditMontant::operator-=() */


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*\
+++++++++++++ CEditMontant::CMExit() +++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+                                                                              +
+    Cette méthode permet de terminer la saisie du montant en le formattant    +
+ correctement.                                                                +
+                                                                              +
+ Paramètres :                                                                 +
+   ignorés.                                                                   +
\*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void __fastcall CEditMontant::CMExit( Controls::TCMExit& Msg)
{
 if( GetTextLen() > 0)
   SetMontant( GetMontant());

 inherited::Dispatch( &Msg);
} /* CEditMontant::CMExit() */

} // namespace Ceditmon */



////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
void __fastcall SetMontantToNDigits(short Nb)
	{
  ASSERT(Nb >= 2);
  ASSERT(Nb <= 4);

	CEditMontant::iNbDecimales = Nb;
	}


bool __fastcall CEditMontant::EstCorrectementRempliDefault( void)
{
  return( !Text.IsEmpty() && (Montant != 0));
}
